package hn.sigit.model.hnd.ladmshadow;

import hn.sigit.logic.geometry.GeometryOperations;
import hn.sigit.logic.ladm.RightsUtil;
import hn.sigit.util.PropertyResponsibilitiesComparable;
import hn.sigit.util.PropertyRestrictionsComparable;
import hn.sigit.util.PropertyRightsComparable;
import hn.sigit.util.ResponsibilitiesComparable;
import hn.sigit.util.RestrictionsComparable;
import hn.sigit.util.RightsComparable;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.persistence.*;

import com.vividsolutions.jts.geom.MultiPolygon;
import com.vividsolutions.jts.geom.Polygon;


@Entity
@org.hibernate.annotations.Proxy(lazy=false)
@Table(name="Property", schema="ladmshadow")
@Inheritance(strategy=InheritanceType.JOINED)
@PrimaryKeyJoinColumn(name="BAUnitID", referencedColumnName="ID")
public class Property extends BAUnit implements Serializable, Cloneable, PropertyRightsComparable, PropertyRestrictionsComparable, PropertyResponsibilitiesComparable {
	private static final long serialVersionUID = 1L;
	
	protected Property() {
	}
	
	public static Property newProperty(Long ladmId, long presentationId, boolean isReadOnly, boolean isSnapshot) {
		Property property = new Property();
		
		property.setLadmId(ladmId);
		property.setPresentationId(presentationId);
		property.setReadOnly(isReadOnly);
		property.setSnapshot(isSnapshot);

		return property;
	}
	
	@Transient
	public Set<Parcel> getParcels() {
		Set<SpatialUnit> suSet = super.getSpatialUnits();
		Set<Parcel> parcelSet = new HashSet<Parcel>();
		
		for (SpatialUnit su : suSet)
			if (su instanceof Parcel)
				parcelSet.add((Parcel)su);
		
		return parcelSet;
	}
	
	@Transient
	public MultiPolygon getParcelsAsMultiPolygon() {
		Set<Parcel> parcels = getParcels();
		
		if (parcels != null && parcels.size() > 0) {
			Polygon[] polygons = new Polygon[parcels.size()];
			int i = 0;
			for (Parcel hndP : parcels)
				polygons[i++] = hndP.getShape();
			
			
			return GeometryOperations.geomFactory.createMultiPolygon(polygons);
		}
		
		return null;
	}

	@Transient
	public String toString() {
		return super.toString();
	}
	
	@Override
	public Property clone() {
		Property clonedProperty;
		try {
			clonedProperty = (Property)super.clone();
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
			return null;
		}
		
		//this is in order to mark the object as unsaved
		clonedProperty.setuID(0);
		
		Set<SpatialSource> spatialSources = new HashSet<SpatialSource>(getSpatialSources());
		
		Set<RRR> rrrSet = new HashSet<RRR>();
		RRR clonedRRR;
		for (RRR rrr : getRrr()) {
			clonedRRR = rrr.clone();
			clonedRRR.setBaunit(clonedProperty);
			rrrSet.add(clonedRRR);
		}
		
		Set<RequiredRelationshipBAUnit> baunits1requiredrelationshipbaunits = new HashSet<RequiredRelationshipBAUnit>(getBaunits1requiredrelationshipbaunits());
		Set<RequiredRelationshipBAUnit> baunits2requiredrelationshipbaunits = new HashSet<RequiredRelationshipBAUnit>(getBaunits2requiredrelationshipbaunits());
		Set<SpatialUnit> spatialUnits = new HashSet<SpatialUnit>(getSpatialUnits());
		Set<AdministrativeSource> adminSources = new HashSet<AdministrativeSource>(getAdminSources());
		
		clonedProperty.setSpatialSources(spatialSources);
		clonedProperty.setRrr(rrrSet);
		clonedProperty.setBaunits1requiredrelationshipbaunits(baunits1requiredrelationshipbaunits);
		clonedProperty.setBaunits2requiredrelationshipbaunits(baunits2requiredrelationshipbaunits);
		clonedProperty.setSpatialUnits(spatialUnits);
		clonedProperty.setAdminSources(adminSources);
		
		return clonedProperty;
	}

	@Transient
	@Override
	public boolean equalPropertyRights(PropertyRightsComparable other) {
		return RightsUtil.propertyRightsEqual(this, other);
	}

	@Transient
	@Override
	public int propertyRightsHash() {
		int hash = 0;
		for (RightsComparable rc : getRightsComparableList())
			hash +=	rc.rightsHash();
		return hash;
	}

	@Transient
	@Override
	public List<RightsComparable> getRightsComparableList() {
		List<RightsComparable> rightsComparableList = new ArrayList<RightsComparable>();
		for (RRR rrr : getRrr())
			if (rrr instanceof RightsComparable)
				if (rrr.getEndLifespanVersion() == null)
					rightsComparableList.add((RightsComparable) rrr);
		return rightsComparableList;
	}

	@Transient
	@Override
	public boolean equalRestrictions(PropertyRestrictionsComparable other) {
		// TODO Auto-generated method stub
		return false;
	}

	@Transient
	@Override
	public int propertyRestrictionsHash() {
		// TODO Auto-generated method stub
		return 0;
	}

	@Transient
	@Override
	public List<RestrictionsComparable> getRestrictionsComparableList() {
		// TODO Auto-generated method stub
		return null;
	}

	@Transient
	@Override
	public boolean equalPropertyResponsibilities(
			PropertyResponsibilitiesComparable other) {
		// TODO Auto-generated method stub
		return false;
	}

	@Transient
	@Override
	public int propertyResponsibilitiesHash() {
		// TODO Auto-generated method stub
		return 0;
	}

	@Transient
	@Override
	public List<ResponsibilitiesComparable> getResponsibilitiesComparableList() {
		// TODO Auto-generated method stub
		return null;
	}
}
